package com.sc.byahi.user.client;

import static com.sc.byahi.user.client.UIUtil.ftInStringToInches;
import static com.sc.byahi.user.client.UIUtil.getCBText;

import java.util.Arrays;
import java.util.List;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextBox;
import com.sc.byahi.user.client.components.HistoryTokens;
import com.sc.byahi.user.client.components.SelectionList;
import com.sc.byahi.user.client.components.SuggestSelectionList;
import com.sc.byahi.user.client.components.rating.NewRating;
import com.sc.byahi.user.shared.SearchBean;
import com.sc.byahi.user.shared.SharedUtil;
import com.sc.byahi.user.shared.constants.Lists;

public class ProfileSearchView extends Composite implements ICleaner {
	private final Label lblSavedSearches = new Label("Saved Searches");
	private final ListBox savedSearchesList = new ListBox();

	private final Label lblRating = new Label(
			"Show profiles rated by me equal or above: (double click any star to clear and search unrated profiles only)");
	private NewRating rating = new NewRating();
	private final Label lblGender = new Label("Gender");

	private final RadioButton rdbtnMale = new RadioButton("gender", "Male");
	private final RadioButton rdbtnFemale = new RadioButton("gender", "Female");
	//
	private final Label lblMaritalStatus = new Label("Marital status");
	private final SelectionList maritalStatusList = new SelectionList();

	private final Label lblPhysicalStatus = new Label("Physical status");
	private final ListBox physicalStatusList = new ListBox();
	//
	private final Label lblAge = new Label("Age");
	private final TextBox txtAgeFrom = new TextBox();
	private final InlineLabel lblAgeFromTo = new InlineLabel("  to  ");
	private final TextBox txtAgeTo = new TextBox();
	//
	private final Label lblHeight = new Label("Height");
	private final ListBox cbHeightFrom = new ListBox();
	private final InlineLabel lblHeightFromTo = new InlineLabel("  to  ");
	private final ListBox cbHeightTo = new ListBox();
	//
	private final Label lblReligion = new Label("Religion");
	private final ListBox cbReligion = new ListBox();
	private final Label lblCaste = new Label("Caste");
	private final SelectionList casteList = new SelectionList();

	private final Label lblMotherTongue = new Label("Mother tongue");
	private final ListBox motherTongueList = new ListBox();

	private final Label lblLanguages = new Label("Languages");
	private final SuggestSelectionList languagesList = new SuggestSelectionList(UIUtil.lists.get(Lists.MOTHER_TONGUE).get(""));

	private final Label lblEatingHabits = new Label("Eating habits");
	private final SelectionList eatingHabitsList = new SelectionList();
	//
	private final Label lblDegrees = new Label("Degrees");
	private final SelectionList degreesList = new SelectionList();
	private final Label lblEmploymentTypes = new Label("Employment types");
	private final SelectionList employmentTypeList = new SelectionList();

	private final Label lblCurrLocation = new Label("Current location");
	private final SuggestSelectionList currLocation = new SuggestSelectionList(UIUtil.lists.get(Lists.COUNTRIES).get(""));

	private final Button search = new Button("Search");
	private final Label lblSaveAndSearch = new Label(
			"If you want to search using same options, please give it a name in following box and click 'Save and Search'.");
	private final TextBox txtSaveSearchName = new TextBox();
	private final Button saveAndSearch = new Button("Save and Search");
	private final Button deleteCurrentSavedSearch = new Button("Delete this saved search");

	public ProfileSearchView() {
		FlexTable tab = new FlexTable();
		tab.setStyleName("my-form");
		tab.setStylePrimaryName("my-form");
		initWidget(tab);
		setStyleName("profile-search-top");

		FlowPanel hp = new FlowPanel();
		int row = 0;

		hp = new FlowPanel();
		hp.add(rdbtnFemale);
		hp.add(rdbtnMale);

		refreshSearchCriteriaList();

		tab.setWidget(row++, 0, lblSavedSearches);
		tab.setWidget(row++, 0, savedSearchesList);

		tab.setWidget(row++, 0, lblGender);
		tab.setWidget(row++, 0, hp);

		tab.setWidget(row++, 0, lblMaritalStatus);
		tab.setWidget(row++, 0, maritalStatusList);

		tab.setWidget(row++, 0, lblPhysicalStatus);
		tab.setWidget(row++, 0, physicalStatusList);

		hp = new FlowPanel();
		hp.add(txtAgeFrom);
		hp.add(lblAgeFromTo);
		hp.add(txtAgeTo);
		txtAgeFrom.setStyleName("age");
		txtAgeTo.setStyleName("age");

		tab.setWidget(row++, 0, lblAge);
		tab.setWidget(row++, 0, hp);

		hp = new FlowPanel();
		hp.add(cbHeightFrom);
		hp.add(lblHeightFromTo);
		hp.add(cbHeightTo);

		tab.setWidget(row++, 0, lblHeight);
		tab.setWidget(row++, 0, hp);

		tab.setWidget(row++, 0, lblReligion);
		tab.setWidget(row++, 0, cbReligion);

		tab.setWidget(row++, 0, lblCaste);
		tab.setWidget(row++, 0, casteList);

		tab.setWidget(row++, 0, lblMotherTongue);
		tab.setWidget(row++, 0, motherTongueList);

		tab.setWidget(row++, 0, lblLanguages);
		tab.setWidget(row++, 0, languagesList);

		tab.setWidget(row++, 0, lblEatingHabits);
		tab.setWidget(row++, 0, eatingHabitsList);

		tab.setWidget(row++, 0, lblDegrees);
		tab.setWidget(row++, 0, degreesList);

		tab.setWidget(row++, 0, lblEmploymentTypes);
		tab.setWidget(row++, 0, employmentTypeList);

		tab.setWidget(row++, 0, lblCurrLocation);
		tab.setWidget(row++, 0, currLocation);

		rating.setMode(true);// no event will be issued if value is changed.
		rating.setDoubleClick(true);// double click will clear ratings.
		tab.setWidget(row++, 0, lblRating);
		tab.setWidget(row++, 0, rating);

		tab.setWidget(row++, 0, search);
		tab.setWidget(row++, 0, new Label());
		tab.setWidget(row++, 0, lblSaveAndSearch);
		txtSaveSearchName.setMaxLength(50);
		tab.setWidget(row++, 0, txtSaveSearchName);
		hp = new FlowPanel();
		hp.add(saveAndSearch);
		hp.add(deleteCurrentSavedSearch);
		tab.setWidget(row++, 0, hp);

		fetchAndFillSelectedSearch();

		attachHandlers();

	}

	private void refreshSearchCriteriaList() {
		List<String> sb = AppController.get().getSbList();
		savedSearchesList.clear();
		savedSearchesList.addItem("");
		for (String string : sb) {
			savedSearchesList.addItem(string);
		}
	}

	@Override
	/**
	 * Removes old values, at least touches every variable so that no stale value remains
	 */
	public void clean() {
		SearchBean sb = new SearchBean();
		sb.setDefaults();
		setValues(sb);
	}

	private void fetchAndFillSelectedSearch() {
		String name = getCBText(savedSearchesList);
		if (!"".equals(name)) {
			GreetingService.Util.getInstance().findSearchCriteria(name, new AsyncCallback<SearchBean>() {

				@Override
				public void onSuccess(SearchBean result) {
					setValues(result);
				}

				@Override
				public void onFailure(Throwable caught) {
					UIUtil.showError();
				}
			});
		} else {
			clean();
		}
	}

	private void attachHandlers() {

		cbReligion.addChangeHandler(new ChangeHandler() {

			@Override
			public void onChange(ChangeEvent event) {
				UIUtil.fillCasteSelectBox(casteList, getCBText(cbReligion));
			}

		});

		search.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				search();
			}
		});

		savedSearchesList.addChangeHandler(new ChangeHandler() {

			@Override
			public void onChange(ChangeEvent event) {
				fetchAndFillSelectedSearch();
			}
		});

		deleteCurrentSavedSearch.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				final String name = getCBText(savedSearchesList);
				if (!"".equals(name)) {
					GreetingService.Util.getInstance().deleteSearchCriteria(name, new AsyncCallback<Void>() {

						@Override
						public void onSuccess(Void result) {
							AppController.get().getSbList().remove(name);
							refreshSearchCriteriaList();
							fetchAndFillSelectedSearch();
						}

						@Override
						public void onFailure(Throwable caught) {
							UIUtil.showError();
						}
					});
				}
			}
		});

		saveAndSearch.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				String name = txtSaveSearchName.getText().trim();
				if ("".equals(name)) {
					UIUtil.showDialog(Arrays.asList("Please give a name to this search option.", "Example: Brides, 25-30"), "Error");
					return;
				}

				final SearchBean sb = new SearchBean();
				collectData(sb);

				GreetingService.Util.getInstance().saveSearchCriteria(sb, new AsyncCallback<Boolean>() {

					@Override
					public void onSuccess(Boolean result) {
						UIUtil.showDialog(
								Arrays.asList("Search successfuly saved. You will see this option in a drop down box on the top of the search page."),
								"Saved");
						// now add this data to appcontroller array.
						AppController.get().getSbList().add(sb.getName());
						refreshSearchCriteriaList();
						search();
					}

					@Override
					public void onFailure(Throwable caught) {
						UIUtil.showError();
					}
				});
			}
		});
	}

	private void search() {
		SearchBean sb = new SearchBean();
		collectData(sb);
		String base64 = UIUtil.encodeSearchBean(sb);
		History.newItem(HistoryTokens.SEARCH_CRITERIA + ":" + base64, false);// so that back brings user to changed page
		History.newItem(HistoryTokens.SEARCH_RESULT + ":" + base64, true);// so that token change works when user clicks search again
	}

	public void setValues(SearchBean sb) {

		rating.setInitValue(sb.getRatingThreshold());
		rdbtnMale.setValue("Male".equals(sb.getGender()) ? true : false);
		rdbtnFemale.setValue("Female".equals(sb.getGender()) ? true : false);

		UIUtil.fillMaritalStatus(maritalStatusList);
		UIUtil.setListValue(maritalStatusList, sb.getMaritalStatus());

		UIUtil.fillPhysicalStatusList(physicalStatusList);
		UIUtil.setListValue(physicalStatusList, Arrays.asList(sb.getPhysicalStatus()));

		txtAgeFrom.setText(sb.getAgeBegin() == null ? "" : sb.getAgeBegin().toString());
		txtAgeTo.setText(sb.getAgeEnd() == null ? "" : sb.getAgeEnd().toString());

		UIUtil.fillHeightList(cbHeightFrom, false);
		if (sb.getHeightBegin() != null)
			UIUtil.setListValue(cbHeightFrom, Arrays.asList(sb.getHeightBegin().toString()));

		UIUtil.fillHeightList(cbHeightTo, true);
		if (sb.getHeightEnd() != null)
			UIUtil.setListValue(cbHeightTo, Arrays.asList(sb.getHeightEnd().toString()));

		UIUtil.fillReligionList(cbReligion);
		UIUtil.setListValue(cbReligion, Arrays.asList(sb.getReligion()));// TODO: set Hindu as default here

		UIUtil.fillCasteSelectBox(casteList, getCBText(cbReligion));
		UIUtil.setListValue(casteList, sb.getCaste());

		UIUtil.fillMothertongueList(motherTongueList);
		// By default no mother tongue is selected
		{
			motherTongueList.insertItem("", 0);
			motherTongueList.setSelectedIndex(0);
		}
		UIUtil.setListValue(motherTongueList, Arrays.asList(sb.getMotherTongue()));

		languagesList.setOptionsData(sb.getLanguages());

		UIUtil.fillDietList(eatingHabitsList);
		UIUtil.setListValue(eatingHabitsList, sb.getEatingHabits());

		UIUtil.fillDegreesList(degreesList);
		UIUtil.setListValue(degreesList, sb.getDegrees());

		UIUtil.fillEmploymentTypeList(employmentTypeList);
		UIUtil.setListValue(employmentTypeList, sb.getEmploymentType());

		currLocation.clean();
		currLocation.setOptionsData(sb.getLocationCountry());

		txtSaveSearchName.setText(sb.getName());
	}

	public void collectData(SearchBean sb) {
		// sb.setProfileID(txtProfileId.getText());
		sb.setName(txtSaveSearchName.getText().trim());
		sb.setRatingThreshold(rating.getValue());
		sb.setGender(rdbtnMale.getValue() ? "Male" : "Female");
		sb.setMaritalStatus(maritalStatusList.getSelectedItems());
		sb.setPhysicalStatus(getCBText(physicalStatusList));
		sb.setAgeBegin(SharedUtil.getLong(txtAgeFrom.getText()));
		sb.setAgeEnd(SharedUtil.getLong(txtAgeTo.getText()));
		sb.setHeightBegin(ftInStringToInches(getCBText(cbHeightFrom)));
		sb.setHeightEnd(ftInStringToInches(getCBText(cbHeightTo)));
		sb.setReligion(getCBText(cbReligion));
		sb.setCaste(casteList.getSelectedItems());
		sb.setMotherTongue(getCBText(motherTongueList));
		sb.setLanguages(languagesList.getSelectedItems());
		sb.setEatingHabits(eatingHabitsList.getSelectedItems());
		sb.setDegrees(degreesList.getSelectedItems());
		sb.setEmploymentType(employmentTypeList.getSelectedItems());
		sb.setLocationCountry(currLocation.getSelectedItems());
	}
}
